# -*- coding: utf-8 -*-
# @Author  : LvShenkai
# @Time    : 2021/9/14 16:41
# @Function: 数据处理函数
import datetime

import numpy
import pandas
from dateutil.parser import parse
from parameter.parameter import Parameter


class DataSet:
    """
        数据集
    """
    min_value = {}  # 保存所有数据的最小值
    max_value = {}  # 保存所有数据的最大值

    @staticmethod
    def data_load(data_list_dic: list, phase='train') -> pandas.DataFrame:
        """
            数据加载

        :param data_list_dic: 元素为字典的数组
        :param phase: 标记，训练数据需要处理，去除脏数据，测试数据不需要处理
        :return:返回得到的数据

        """

        # 取data_list_dic中字典所有的key，即列名
        columns = []  # 列名存储
        dic_0 = data_list_dic[0]
        for key in dic_0.keys():
            columns.append(key)

        df = pandas.DataFrame(columns=columns)  # 创建新的DataFrame
        df_index = 0

        # 循环遍历data_list_dic，将数据添加到df中
        for dic in data_list_dic:
            df_add = []  # 添加到df中的一行数据
            for column in columns:
                if column == 'DOW' and phase != 'center':  # 将日期转换为周几，用0.1-0.7表示周一到周日
                    element = float(dic[column]) / 10
                # if column == 'FLIGHTDATE':
                #     element = parse(dic[column])
                else:  # 其余数据直接转化
                    element = dic[column]
                    if element is None:
                        element = 0
                df_add.append(element)

            df.loc[df_index] = df_add  # 新数据行加入df
            df_index += 1

        # 删除'ITTL0'和'ITTLN1'为0的数据
        if phase != 'center':
            df = df[-df.ITTL0.isin([0])]
            df = df[-df.ITTLN1.isin([0])]
        if phase == 'train':
            # 补全非ttl0和ttln1处为0的数据。
            # 即在一行数据中，只有其中一个数字为0，则用前后的数据均值补全。ttl0和ttln1为0则不用补全
            columns_ttl = Parameter.COLUMNS_NORMALIZATION.value
            # 遍历每行数据
            delete_indexs = []  # 连续两个ttl都是0的数据删除，记录下标
            for index, row in df.iterrows():
                for i in range(1, len(columns_ttl) - 1):
                    pre = row[columns_ttl[i - 1]]  # 前一个
                    cur = row[columns_ttl[i]]  # 当前ttl的数
                    after = row[columns_ttl[i + 1]]  # 后一个数
                    if cur == 0:
                        if after == 0:  # 连续两个都是0，则加入删除数组，删除这一行数据
                            delete_indexs.append(index)
                            break
                        cur = (pre + after) / 2
                        df.at[index, columns_ttl[i]] = cur

            ttln1_array = numpy.array(df['ITTLN1'].tolist())
            mu = ttln1_array.mean()
            std = ttln1_array.std()
            df = df[numpy.abs(df['ITTLN1'] - mu) < 2.5 * std]
            df.reset_index(drop=True,inplace=True)

        return df

    @staticmethod
    def df_2_dic_list(df: pandas.DataFrame) -> list:
        """
            将DataFrame数据转换为由字典组成的数组格式，其中每个字典存储一行DataFrame数据
        :param df: 要转换的DataFrame
        :return: 由字典组成的数组
        """
        num = df.shape[0]  # 数据行数
        columns = df.columns.tolist()  # 列名
        dic_list = []  # 由字典组成的数组
        # 遍历每行df，转换成字典并存入到dic_list
        for index in range(num):
            dic = {}
            s = df.iloc[index]
            for column in columns:
                dic[column] = s[column]
            dic_list.append(dic)

        return dic_list

    @staticmethod
    def classify_train_and_test(data: pandas.DataFrame):
        pass

    @staticmethod
    def normalization(df_data: pandas.DataFrame):
        """
            df数据规一化
            通过公式(x-min)/(max-min)归一化到[0,1]之间
        :param df_data: DataFrame数据
        :return: 返回归一化后的df数据,最大值和最小值
        """
        columns = df_data.columns.tolist()  # 列名
        # 获取最大、最小值
        for column in columns:
            if column in Parameter.COLUMNS_NORMALIZATION.value:
                if column in DataSet.min_value:
                    continue
                s = df_data[column].unique()  # 读取每列数据
                min_s = min(s)  # 当前列的最小值
                max_s = max(s)  # 当前列的最大值
                DataSet.min_value[column] = min_s
                DataSet.max_value[column] = max_s

        # 归一化
        for column in columns:
            if column in Parameter.COLUMNS_NORMALIZATION.value:
                min_value = DataSet.min_value[column]
                max_value = DataSet.max_value[column]
                if (max_value - min_value) > 0:
                    df_data[column] = (df_data[column] - min_value) / (max_value - min_value)

        return df_data

    @staticmethod
    def reverse_normalization(df_data):
        """
            反规一化
            通过公式(max-min)*x+min反规一化
        :param df_data: 要反归一化的数据
        :return: 反归一化后的数据df
        """
        min_value = DataSet.min_value
        max_value = DataSet.max_value
        columns = df_data.columns.tolist()  # 列名
        for column in columns:
            if column in Parameter.COLUMNS_NORMALIZATION.value:
                df_data[column] = (max_value[column] - min_value[column]) * df_data[column] + min_value[column]

        return df_data


if __name__ == '__main__':
    data_list_dic_1 = [
        {'FLIGHTDATE': datetime.datetime(2018, 7, 19, 0, 0),
         'ITTL360': None, 'ITTL180': None, 'ITTL90': None, 'ITTL55': None, 'ITTL45': None, 'ITTL35': None,
         'ITTL28': None, 'ITTL25': None, 'ITTL22': None, 'ITTL19': None, 'ITTL17': None, 'ITTL15': None,
         'ITTL13': None, 'ITTL11': None, 'ITTL9': None, 'ITTL8': None, 'ITTL7': None, 'ITTL6': None,
         'ITTL5': None, 'ITTL4': None, 'ITTL3': None, 'ITTL2': 1, 'ITTL1': 5, 'ITTL0': 10,
         'ITTLN1': 356},
        {'FLIGHTDATE': datetime.datetime(2018, 7, 21, 0, 0),
         'ITTL360': None, 'ITTL180': None, 'ITTL90': None, 'ITTL55': None, 'ITTL45': None, 'ITTL35': None,
         'ITTL28': None, 'ITTL25': None, 'ITTL22': None, 'ITTL19': None, 'ITTL17': None, 'ITTL15': None,
         'ITTL13': None, 'ITTL11': None, 'ITTL9': None, 'ITTL8': None, 'ITTL7': None, 'ITTL6': None,
         'ITTL5': None, 'ITTL4': None, 'ITTL3': None, 'ITTL2': 4, 'ITTL1': 6, 'ITTL0': 8,
         'ITTLN1': 316},
        {'FLIGHTDATE': datetime.datetime(2018, 7, 24, 0, 0),
         'ITTL360': None, 'ITTL180': None, 'ITTL90': None, 'ITTL55': None, 'ITTL45': None, 'ITTL35': None,
         'ITTL28': None, 'ITTL25': None, 'ITTL22': None, 'ITTL19': None, 'ITTL17': None, 'ITTL15': None,
         'ITTL13': None, 'ITTL11': None, 'ITTL9': None, 'ITTL8': None, 'ITTL7': None, 'ITTL6': None,
         'ITTL5': None, 'ITTL4': None, 'ITTL3': None, 'ITTL2': None, 'ITTL1': 56, 'ITTL0': 111,
         'ITTLN1': 216},
        {'FLIGHTDATE': datetime.datetime(2018, 7, 25, 0, 0),
         'ITTL360': None, 'ITTL180': None, 'ITTL90': None, 'ITTL55': None, 'ITTL45': None, 'ITTL35': None,
         'ITTL28': None, 'ITTL25': None, 'ITTL22': None, 'ITTL19': None, 'ITTL17': None, 'ITTL15': None,
         'ITTL13': None, 'ITTL11': None, 'ITTL9': None, 'ITTL8': None, 'ITTL7': None, 'ITTL6': None,
         'ITTL5': None, 'ITTL4': None, 'ITTL3': 1, 'ITTL2': 23, 'ITTL1': 67, 'ITTL0': 115,
         'ITTLN1': 218}
    ]
    df = DataSet.data_load(data_list_dic_1)

    a = DataSet.df_2_dic_list(df)
    print(a)

    # print(columns)
